<template>
  <view class="i-tag">
    <view
      class="titleView"
      :style="{ width: `calc(100% - ${viewPadding} - ${viewPadding})` }"
      v-if="isScroll"
    >
      <scroll-view
        :scroll-x="true"
        :scroll-with-animation="true"
        :scroll-left="scrollLeft"
        class="scroll-view"
        :style="{ textAlign: center ? 'center' : '', overflowX }"
      >
        <view
          class="scroll_view_item"
          :style="{
            width,
            fontSize: size + viewStyle.type,
            marginRight: left + 'px',
            color:
              modelValue === index ? viewStyle.activeColor : viewStyle.dColor,
          }"
          @click.stop="handleClick(index)"
          v-for="(item, index) in list"
          :key="index"
          :class="{ activeItem: modelValue === index }"
        >
          {{ item.title }}
        </view>
      </scroll-view>
    </view>
    <view class="static_view" v-else>
      <view
        v-for="(item, index) in list"
        :key="index"
        class="static_view_item"
        :style="{
          fontSize: size + viewStyle.type,
          color:
            modelValue === index ? viewStyle.activeColor : viewStyle.dColor,
          textAlign: 'center',
          // width: lineWidth + 'vw',
        }"
        @click.stop="handleClick(index)"
        :class="{ staticActiveItem: modelValue === index }"
      >
        <view
          :style="{
            borderBottom:
              modelValue === index
                ? `${linHeight} solid ${viewStyle.activeColor}`
                : `${linHeight} solid transparent`,
          }"
          >{{ item.title }}</view
        >
      </view>
    </view>

    <view
      v-if="isScroll"
      class="line"
      :style="{
        marginLeft: viewPadding,
        height: linHeight,
        transform: 'translateX(' + (translateX - lineWidth) + 'px)',
        width: lineWidth + 'px',
        marginTop: margin,
      }"
    ></view>
    <view :style="{ padding }"></view>
    <view v-if="show_line" class="show_line"></view>
    <slot name="topSlot"></slot>
  </view>
</template>

<script lang="ts" setup>
import {
  ref,
  defineProps,
  defineEmits,
  onMounted,
  getCurrentInstance,
  watch,
  computed,
} from "vue";
import _ from "lodash";

const lineWidth = ref(30);
const listWidth = ref([]);
const translateX = ref(30);
const scrollLeft = ref(0);

const defaultViewStyle = {
  width: 98,
  right: 42,
  activeColor: "#FF9400",
  type: "rpx",
  dColor: "#16161F",
};

const props = defineProps({
  isScroll: {
    type: Boolean,
    default: true,
  },
  width: {
    type: String,
    default: "",
  },
  overflowX: {
    type: String,
    default: "auto",
  },
  show_line: {
    type: [Boolean, String],
    default: false,
  },
  left: {
    type: Number,
    default: 16,
  },
  list: {
    type: Array,
    default: () => [],
  },
  size: {
    type: [String, Number],
    default: "32",
  },
  center: {
    type: Boolean,
    default: false,
  },
  viewPadding: {
    type: String,
    default: "24rpx",
  },
  margin: {
    type: String,
    default: "-15px",
  },
  linHeight: {
    type: String,
    default: "8rpx",
  },
  viewStyleData: {
    type: Object,
    default: () => {},
  },
  modelValue: {
    type: Number,
    default: 0,
  },
  padding: {
    type: String,
    default: "0",
  },
});

const viewStyle = computed(() => {
  return { ...defaultViewStyle, ...props.viewStyleData };
});

const emit = defineEmits(["update:modelValue", "change"]);

const handleClic = (i: number) => {
  emit("update:modelValue", i);
  emit("change", i);
};
const handleClick = _.debounce(handleClic, 300, {
  leading: true,
  trailing: false,
});

onMounted(() => {
  const refs = uni.createSelectorQuery().in(getCurrentInstance()?.proxy);
  refs
    .selectAll(".scroll_view_item")
    .boundingClientRect((data: { width: number; left: number }[]) => {
      listWidth.value = data;
      if (props.modelValue) {
        lineWidth.value = data[props.modelValue].width;
        getTranslateX(props.modelValue);
      } else {
        lineWidth.value = data[0]?.width || 30;
        translateX.value = data[0]?.width || 30;
      }
    })
    .exec();
});

watch(
  () => props.modelValue,
  (val) => {
    if (listWidth.value.length) {
      lineWidth.value = listWidth.value[val]?.width;
      getTranslateX(val);
    }
  }
);

const getTranslateX = (index: number) => {
  let w = 0;
  for (let i = 0; i <= index; i++) {
    w += listWidth.value[i].width;
  }

  const currentItem = listWidth.value[index];
  const windowWidth = uni.getSystemInfoSync().windowWidth;
  const itemCenter = currentItem.left + currentItem.width / 2;

  // 计算 scroll-view 需要滚动到的位置
  scrollLeft.value = Math.max(0, itemCenter - windowWidth / 2);

  // 计算 scroll-view 最多能滚动的距离
  const lastItem = listWidth.value[listWidth.value.length - 1];
  const maxScrollLeft = lastItem.left + lastItem.width - windowWidth;

  // 判断是否已滚到底部
  const isEndReached = scrollLeft.value >= maxScrollLeft;

  const leftTotal = w + props.left * index - scrollLeft.value;
  if (!isEndReached) {
    translateX.value = leftTotal;
  } else {
    // 到底部时对指示条位置进行补偿调整
    // 当滚动到底部时，scrollLeft被限制在maxScrollLeft

    // 1. 计算理想滚动位置与实际滚动位置的差值
    const idealScrollLeft = itemCenter - windowWidth / 2;
    const actualScrollLeft = maxScrollLeft; // 滚到底部时，实际滚动值就是最大值
    const scrollDiff = idealScrollLeft - actualScrollLeft;

    // 2. 应用补偿，但减少10px的过度补偿
    const viewPaddingValue = Number(
      props.viewPadding.toString().replace(/(px|rpx|%)$/, "")
    );
    console.log(viewPaddingValue, "viewPaddingValue");

    const compensationOffset =
      scrollDiff > 0 ? scrollDiff - viewPaddingValue - 4 : 0;

    // 3. 计算最终位置
    translateX.value = leftTotal + compensationOffset;
  }
};
</script>

<style lang="scss" scoped>
.i-tag {
  width: 100%;
  position: relative;

  .static_view {
    @include flexRS;
    box-sizing: border-box;
    padding: 12rpx 32rpx;

    .static_view_item {
      white-space: nowrap;
      overflow: hidden;
      transition: 0.3s ease-in all;
      margin: 0 12rpx;
      padding-bottom: 4rpx;
      view {
        display: inline-block;
      }
    }
  }
  .titleView {
    margin: 0 auto;
  }
  .scroll-view {
    display: flex;
    white-space: nowrap;

    .scroll_view_item {
      height: 52px;
      display: inline-block;
      font-weight: 400;
      font-family: PingFangSC-Regular, PingFang SC;
      white-space: nowrap;
      line-height: 52px;
      text-align: center;
    }
  }

  .line {
    position: absolute;
    background-image: linear-gradient(to right, #fb9e5f, #f56531);
    transition: all linear 0.2s;
    z-index: 10;
  }
}

.activeItem {
  font-weight: bold !important;
  color: $dcolor;
}

.show_line {
  width: 100%;
  height: 1rpx;
  background-color: #e6e6f0;
}
.staticActiveItem {
  border-bottom-color: #f56531 !important;
  font-weight: bold;
}

/* 隐藏 scroll-view 的滚动条 */
.scroll-view ::-webkit-scrollbar {
  display: none !important;
  width: 0;
  height: 0;
  color: transparent;
}
</style>
